package org.genntii.smuserserver.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.jsonwebtoken.Claims;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import org.genntii.smcommon.constant.ClientConstant;
import org.genntii.smcommon.constant.ExceptionConstant;
import org.genntii.smcommon.exception.UserNotFoundException;
import org.genntii.smcommon.properties.JwtProperties;
import org.genntii.smcommon.result.PageResult;
import org.genntii.smcommon.utils.DateUtil;
import org.genntii.smcommon.utils.JwtUtil;
import org.genntii.smdomain.doc.VO.UserDocVO;
import org.genntii.smdomain.dto.UserDTO;
import org.genntii.smdomain.dto.UserUpdateDTO;
import org.genntii.smdomain.entity.User;
import org.genntii.smdomain.vo.ArticleVO;
import org.genntii.smdomain.vo.CommentClientVO;
import org.genntii.smdomain.vo.CommentVO;
import org.genntii.smdomain.vo.UserVO;
import org.genntii.smuserserver.client.ArticleClient;
import org.genntii.smuserserver.client.CommentClient;
import org.genntii.smuserserver.client.UserSubscribeClient;
import org.genntii.smuserserver.mapper.ArticleCommentMapper;
import org.genntii.smuserserver.mapper.UserMapper;
import org.genntii.smuserserver.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private UserSubscribeClient userSubscribeClient;

    @Resource
    private UserMapper userMapper;

    @Resource
    private JwtProperties jwtProperties;

    @Resource
    private ArticleCommentMapper articleCommentMapper;

    @Resource
    private ArticleClient articleClient;

    @Resource
    private CommentClient commentClient;

    @Resource
    private MongoTemplate mongoTemplate;

    @Override
    public UserDocVO getUserDocVOById(Long userId) {
        User user = userMapper.selectById(userId);
        if (user==null){
            throw new UserNotFoundException(ExceptionConstant.USER_NOT_FOUND_EXCEPTION);
        }
        return UserDocVO.builder()
                .id(userId)
                .username(user.getUsername())
                .nickname(user.getNickname())
                .avatar(user.getAvatar())
                .build();
    }

    @Override
    public void updateUser(UserDTO userDTO) {
        userMapper.updateUser(userDTO.getNickname(),
                userDTO.getDescription(),
                userDTO.getPhone(),
                userDTO.getAvatar(),
                userDTO.getBirthday(),
                userDTO.getGender(),
                userDTO.getBackgroundImage(),
                userDTO.getId());
    }

    @Override
    public void insertSteamId(Long steamId, Long userId) {

        userMapper.updateSteamId(steamId,userId);
    }

    @Override
    public Boolean userExists(String username) {
        if (userMapper.usernameIsExist(username)>0){
            return true;
        }else {
            throw new UserNotFoundException(ExceptionConstant.USER_NOT_FOUND_EXCEPTION);
        }

    }

    @Override
    public UserVO getUserById(Long userId) {
        User user = userMapper.selectById(userId);

        if (user == null) {
            throw new UserNotFoundException(ExceptionConstant.USER_NOT_FOUND_EXCEPTION);
        }

        UserVO userVO = UserVO.builder()
                .id(userId)
                .username(user.getUsername())
                .nickname(user.getNickname())
                .email(user.getEmail())
                .avatar(user.getAvatar())
                .gender(user.getGender())
                .cityCode(user.getCityCode())
                .description(user.getDescription())
                .backgroundImage(user.getBackgroundImage())
                .subscriberCount(userSubscribeClient.getSubscribeNum(user.getId()).getData().getSubscribedNum())
                .followerCount(userSubscribeClient.getSubscribeNum(user.getId()).getData().getSubscribeNum())
                .steamId(String.valueOf(user.getSteamid()))
                .build();
        if (user.getBirthday() != null){
            DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            userVO.setBirthday(user.getBirthday().format(fmt));
        }
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        userVO.setLoginTime(user.getLoginTime().format(fmt));
        userVO.setCreateTime(user.getCreateTime().format(fmt));
        return userVO;
    }

    @Override
    public UserVO dcGetUserById(Long targetId, Long userId) {
        User user = userMapper.selectById(targetId);

        if (user == null) {
            throw new UserNotFoundException(ExceptionConstant.USER_NOT_FOUND_EXCEPTION);
        }
        UserVO userVO = UserVO.builder()
                .id(targetId)
                .username(user.getUsername())
                .nickname(user.getNickname())
                .email(user.getEmail())
                .avatar(user.getAvatar())
                .gender(user.getGender())
                .cityCode(user.getCityCode())
                .description(user.getDescription())
                .backgroundImage(user.getBackgroundImage())
                .subscriberCount(userSubscribeClient.getSubscribeNum(user.getId()).getData().getSubscribedNum())
                .followerCount(userSubscribeClient.getSubscribeNum(user.getId()).getData().getSubscribeNum())
                .steamId(user.getSteamid()!=null?String.valueOf(user.getSteamid()):null)
                .subscribed(targetId != userId?userSubscribeClient.userSubscribed((byte) 2,targetId,userId).getData():null)
                .build();
        if (user.getBirthday() != null){
            DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            userVO.setBirthday(user.getBirthday().format(fmt));
        }
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        userVO.setLoginTime(user.getLoginTime().format(fmt));
        userVO.setCreateTime(user.getCreateTime().format(fmt));
        return userVO;
    }

    @Override
    public Map<Long, UserVO> getUserListMapByIds(ArrayList<Long> userIds) {
        List<User> userList = userMapper.selectList(new QueryWrapper<User>().in("id", userIds));
        Map<Long, UserVO> userMap = new HashMap<>();

        for (User user : userList) {
            UserVO userVO = new UserVO();
            BeanUtils.copyProperties(user, userVO);
            userVO.setFollowerCount(userSubscribeClient.getSubscribeNum(user.getId()).getData().getSubscribeNum());
            userVO.setSubscriberCount((userSubscribeClient.getSubscribeNum(user.getId()).getData().getSubscribedNum()));
            userMap.put(user.getId(), userVO);
        }

        return userMap;
    }

    @Override
    public Boolean steamIdExists(String token, String client) {
        Claims claims = switch (client) {
            case ClientConstant.ADMIN_CLIENT -> JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);
            case ClientConstant.USER_CLIENT -> JwtUtil.parseJWT(jwtProperties.getUserSecretKey(), token);
            case ClientConstant.DEVELOPER_CLIENT -> JwtUtil.parseJWT(jwtProperties.getDevSecretKey(), token);
            default -> throw new RuntimeException("token异常");
        };
        Long id = Long.valueOf(String.valueOf(claims.get("id")));
//        QueryWrapper<User> user = new QueryWrapper<User>().eq("id",id);
        User u = userMapper.selectById(id);
        if (u == null){
            throw new UserNotFoundException(ExceptionConstant.USER_NOT_FOUND_EXCEPTION);
        }else return u.getSteamid() != null;

    }

    @Override
    public PageResult<ArticleVO> getArticle(Integer pageSize, Integer pageNum, Long userId) {
        return PageResult.build(articleClient.getArticleLimit(userId,pageNum,pageSize).getData(),
                articleClient.getTotal(userId).getData());
    }

    @Override
    public PageResult<CommentVO> getComment(Integer pageSize, Integer pageNum, Long userId) {
        String nickname = userMapper.getNickNameById(userId);
        ArrayList<CommentClientVO> comments = commentClient.getCommentLimit(userId,pageNum,pageSize).getData();
        ArrayList<CommentVO> commentVOS = new ArrayList<>();
        Map<Long, ArticleVO> articleIdArticleVOMap = new HashMap<>();
        ArrayList<Long> commentArticleIdList = new ArrayList<>();
        for (CommentClientVO comment:comments){
            commentArticleIdList.add(comment.getArticleId());
        }
        if (commentArticleIdList.isEmpty()){
            return PageResult.build(null,0);
        }
        ArrayList<ArticleVO> articleVOS = articleClient.getArticleVOByIds(commentArticleIdList,userId).getData();

        for (ArticleVO articleVO:articleVOS){
            articleIdArticleVOMap.put(articleVO.getId(),articleVO);
        }

        for (CommentClientVO comment:comments){
            CommentVO commentVO = CommentVO.builder()
                    .id(comment.getId())
                    .articleId(comment.getArticleId())
                    .userId(comment.getUserId())
                    .nickname(nickname)
                    .content(comment.getContent())
                    .cityName(comment.getCityName())
                    .createTime(DateUtil.parseDateTime(comment.getCreateTime()))
//                    .like(comment.)
                    .replyArticle(articleIdArticleVOMap.get(comment.getArticleId()))
                    .build();
            commentVOS.add(commentVO);
        }
        return PageResult.build(commentVOS,commentClient.getTotal(userId).getData());
    }

    @Override
    public UserVO updateUserMessage(UserUpdateDTO userUpdateDTO, Long userId) {

        if (userMapper.userIdExists(userId) != 1){
            throw new UserNotFoundException(ExceptionConstant.USER_NOT_FOUND_EXCEPTION);
        }
        LocalDate birthday = null;
        System.out.println(userUpdateDTO.getBirthday());
        if (userUpdateDTO.getBirthday() != null&&userUpdateDTO.getBirthday() != ""){
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            birthday = LocalDate.parse(userUpdateDTO.getBirthday(),dtf);
        }

//        userMapper.updateUserMessage(userUpdateDTO.getNickname(),
//                userUpdateDTO.getDescription(),
//                userUpdateDTO.getEmail(),
//                userUpdateDTO.getAvatar(),
//                birthday,userUpdateDTO.getGender(),
//                userUpdateDTO.getBackgroundImage(),userId);
        User user = userMapper.selectById(userId);
        user.setNickname(userUpdateDTO.getNickname());
        user.setDescription(userUpdateDTO.getDescription());
        user.setEmail(userUpdateDTO.getEmail());
        user.setAvatar(userUpdateDTO.getAvatar());
        user.setBirthday(birthday);
        user.setGender(String.valueOf(userUpdateDTO.getGender()));
        user.setBackgroundImage(userUpdateDTO.getBackgroundImage());
        userMapper.updateById(user);

        UserVO userVO = new UserVO();
        userVO.setId(user.getId());

        return getUserById(userId);
    }
}
